package com.application.fabric.加密算法;

import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;


public class RSA2 {
    private static final String ALGORITHM = "RSA";
    private static String publicpath;
    private static String privatepath;
    private static String UTF_8 = StandardCharsets.UTF_8.name();

    private static final int MAX_DECRYPT_SIZE = 128;

    private static final int MAX_ENCRYPT_SIZE = 117;

    static {

        ClassLoader c1 = RSA2.class.getClassLoader();

        publicpath = c1.getResource("templates/rsa.pub").getPath();

        privatepath = c1.getResource("templates/rsa.pri").getPath();
    }
    /*加密
    * */
    public static String encrypt(String originalCont, Key key) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] bytes = doCodec(cipher,originalCont.getBytes(UTF_8),MAX_ENCRYPT_SIZE);
        return Base64.getEncoder().encodeToString(bytes);
    }

    /*解密
     * */
    public static String decrypt(String encryptStr, Key key) throws Exception {
        byte[] decodeBase64 = Base64.getDecoder().decode(encryptStr);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE,key);
        byte[] decryteBytes =  doCodec(cipher,decodeBase64,MAX_DECRYPT_SIZE);
        return new String(decryteBytes);
    }
    private static byte[] doCodec(Cipher cipher, byte[] bytes,int maxBlockSize) throws Exception{
        int len = bytes.length;
        /*偏移量*/
        int offset = 0;
        byte[] cache;
        int i =0;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        while (len-offset > 0){
            if (len-offset>maxBlockSize){
                cache = cipher.doFinal(bytes,offset,maxBlockSize);
            }else {
                cache = cipher.doFinal(bytes,offset,len-offset);
            }
            byteArrayOutputStream.write(cache,0,cache.length);
            i++;
            offset = i*maxBlockSize;
        }
        byte[] codeBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return codeBytes;
    }

    /*读取公钥
    * */
    private PublicKey getPublicKey() throws Exception{
        String publicKeyBase43str = FileUtils.readFileToString(new File(publicpath), UTF_8);
        byte[] decodeBase64 = Base64.getDecoder().decode(publicKeyBase43str);

        /*公钥x509*/
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodeBase64);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(x509EncodedKeySpec);
    }

    /*读取私钥
     * */
    private PrivateKey getPrivateKey() throws Exception{
        String privateKeyBase43str = FileUtils.readFileToString(new File(privatepath), UTF_8);
        byte[] decodeBase64 = Base64.getDecoder().decode(privateKeyBase43str);

        /*私钥 kspc*/
//        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodeBase64);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decodeBase64);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    }

    /**
     * 写入key
     * */
    private void writeKey() throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(1024);
        /*生成 keypair
        * */
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        /*加密转字节
        * */
        byte[] publicKeyEncode = publicKey.getEncoded();

        /*base64
        * */
        String publicKeyBase64Str =Base64.getEncoder().encodeToString(publicKeyEncode);

        /*私钥
        * */
        PrivateKey privateKey = keyPair.getPrivate();
        /*加密转字节
         * */
        byte[] privateKeyEncode = privateKey.getEncoded();

        /*base64
         * */
        String privateKeyBase64Str =Base64.getEncoder().encodeToString(privateKeyEncode);

        System.out.println(publicKeyBase64Str);
        System.out.println(privateKeyBase64Str);

        FileUtils.writeStringToFile(new File(publicpath),publicKeyBase64Str,UTF_8);
        FileUtils.writeStringToFile(new File(privatepath),privateKeyBase64Str,UTF_8);

    }

    @Test
    public void test() throws Exception{
//        writeKey();
//        System.out.println(getPrivateKey());
//        System.out.println(getPublicKey());

        /*公钥加密私钥解密
        * */
        String str = "kasfoiuhoeihfopeiwfj";
        String  encryptStr = encrypt(str,getPublicKey());
        System.out.println("加密后："+encryptStr);

        String decryptStr = decrypt(encryptStr,getPrivateKey());
        System.out.println("解密后："+decryptStr);

        String  encryptStr1 = encrypt(str,getPrivateKey());
        System.out.println("加密后："+encryptStr1);

        String decryptStr1 = decrypt(encryptStr1,getPublicKey());
        System.out.println("解密后："+decryptStr1);


    }

}
